#include "dpLibrary\graphics.h"
#include "dpLibrary\dpWindows.h"

#include "winlib.h"
#include "AFObjectFactory.h"
#include "AFGraphics.h"
#include <time.h>

// Individual function for printing a single object	
// Creates a buffer for sprite and fills it with a particular color.

extern dpPixel* screenBuffer;

// This function exists to ensure that the global screen buffer is initialized 
// properly.
dpPixel* AFInitializeGraphics()
{
  dpPixel* buffer = (dpPixel*)malloc(dpScreenWidth * dpScreenHeight * 
    sizeof(dpPixel));

  return buffer;
}

// Draws a sprite object to the screen.
void DrawSprite(Sprite* currentSprite)
{
  int x = 0;
  int	y = 0;	

  int finishX = currentSprite->screen.X + currentSprite->width;
  int finishY = currentSprite->screen.Y + currentSprite->height;

  // Determines the coordinate where the sprite will begin
  // to be drawn.  The sprite cannot be drawn in negative coordinates on
  // the window.
  int startSpriteX = max(0, currentSprite->screen.X);
  int startSpriteY = max(0, currentSprite->screen.Y);

  // Determines the coordinate where the sprite will end being 
  // drawn.  The sprite cannot be drawn outside of the window's limits.
  finishX = min(dpScreenWidth, finishX);
  finishY = min(dpScreenHeight, finishY);

  for (y = startSpriteY; y < finishY; y++)
  {
    for(x = startSpriteX; x < finishX; x++)
    {
      *(screenBuffer + (x) + (y) * dpScreenWidth) = currentSprite->color;
    }
  }
}

// Fills the screen with white.
void ClearBuffer()
{
  int x = 0;
  int y = 0;
  for(y = 0; y < dpScreenHeight; ++y)
  {
    for(x = 0; x < dpScreenWidth; ++x)
    {
      *(screenBuffer + x + y * dpScreenWidth) = WHITE;
    }
  }
}

// Draws a random object onto the screen without permanently allocating
// memory.
void DrawObject(int color, int x, int y, int h, int w)
{
  Sprite drawingSprite;
  drawingSprite.color      = color;
  drawingSprite.screen.X = x;
  drawingSprite.screen.Y = y;
  drawingSprite.height     = h;
  drawingSprite.width      = w;
  drawingSprite.next       = NULL;

  DrawSprite(&drawingSprite);
}

// Move Camera function
// Alters the screen coordinates of the sprites
void MoveCamera(Sprite* currentSprite)
{
  // 
}

// Draws an interesting checkered pattern on the screen.
void CheckeredPattern()
{  
  int x=0;
  int y=0;
  for(y=0; y < dpScreenHeight; ++y)
  {
    for(x=0; x< dpScreenWidth; ++x)
    {
      if(y % 2 == 0 )
      {
        if(x % 2 == 0)
        {
          *(screenBuffer+ x + y * dpScreenWidth) = BLACK;
        }
      }
      if(y % 2 == 1)
        if(x % 2 == 1)
        {
          *(screenBuffer + x + y * dpScreenWidth) = BLACK;
        }
    }
  }
}

// Draws a center guideline as reference.
void DrawCenterGuideLine(Sprite* character)
{
  int x = 0;
  int y = 0;

  for(y = 0; y < dpScreenHeight; y++)
  {
    *(screenBuffer + 160 + y * dpScreenWidth) = BLUE;       
  }
}

// Draws a line upward from the player sprite, stops drawing when it hits
// an enemy object.
void FireUpward(Sprite* character)
{
  int x = CENTER_OF_SCREEN_X;
  int y = 0;

  for(y = character->screen.Y - 1; y > 0; --y)
  {
    if(*(screenBuffer + ((dpScreenWidth / 2) + (character->width / 2)) 
      + y * dpScreenWidth) == WHITE)
    {
      *(screenBuffer + ((dpScreenWidth / 2) + (character->width / 2))
        + y * dpScreenWidth) = BLUE;       
    }    
    else
    {
      break;
    }
  }
}

// Print all of the objects on screen
// Gets the buffers for each sprite and prints them to the screen.
void UpdateGraphics(Sprite* playerSprite, Sprite* currentSprite)
{ 
  // Takes the head pointer from our linked list.
  if(currentSprite)
  {
    while(currentSprite)
    {
      currentSprite->screen.X = 
        ((currentSprite->world.X - playerSprite->world.X) + 
        (dpScreenWidth / 2));

      currentSprite->screen.Y = 
        ((currentSprite->world.Y - playerSprite->world.Y) + 
        (dpScreenHeight / 2));

      // Print the current sprite.      
      DrawSprite(playerSprite);
      DrawSprite(currentSprite);
      // If the next pointer doesn't equal null, shift to the next node
      currentSprite = currentSprite->next;			
    }
  }

  
}

void PrintRandomSprites()
{
  /* initialize random seed: */
  int x = rand() % 310 + 1;
  int y = rand() % 310 + 1; 

  srand ((unsigned int)time(NULL)); 

  DrawObject(BLACK, x, y, 10, 10);  
}